package cn.aiweiyi.qingjing.coupon.settlement.executor;

import cn.aiweiyi.qingjing.coupon.comm.constant.CouponCategory;
import cn.aiweiyi.qingjing.coupon.comm.exception.CouponException;
import cn.aiweiyi.qingjing.coupon.comm.vo.SettlementInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 青衿
 * @Date 2020/11/26 19:30
 **/
@Slf4j
@Component
public class ExecuteManager implements BeanPostProcessor {
    /**
     * 规则执行器映射
     */
    private static Map<CouponCategory, RuleExecutor> executorMap =
            new HashMap<>(CouponCategory.values().length);

    /**
     * 优惠券结算规则计算入口
     * 注意:一定要保证传递进来的优惠个数 >=1
     *
     * @param settlement
     * @return
     */
    public SettlementInfo computeRule(SettlementInfo settlement)
            throws CouponException {
        SettlementInfo result = null;
        //单类优惠券
        if (settlement.getCouponAndTemplateInfos().size() == 1) {
            //获取优惠券的类别
            CouponCategory category = CouponCategory.of(
                    settlement.getCouponAndTemplateInfos().get(0)
                            .getTemplate().getCategory()
            );

            switch (category) {
                case MANJIAN:
                    result = executorMap.get(CouponCategory.MANJIAN).computeRule(settlement);
                    break;

                case ZHEKOU:
                    result = executorMap.get(CouponCategory.ZHEKOU).computeRule(settlement);
                    break;

                case LIJIAN:
                    result = executorMap.get(CouponCategory.LIJIAN).computeRule(settlement);
                    break;

                case MANJIAN_ZHEKOU:
                    result = executorMap.get(CouponCategory.MANJIAN_ZHEKOU).computeRule(settlement);
                    break;
            }
        } else {
            //多类优惠券
            List<CouponCategory> categories = new ArrayList<>(
                    settlement.getCouponAndTemplateInfos().size()
            );

            settlement.getCouponAndTemplateInfos().forEach(ct ->
                    categories.add(CouponCategory.of(
                            ct.getTemplate().getCategory()
                    )));

            if (categories.size() != 2) {
                throw new CouponException("不支持更多优惠券模板类型同时叠加");
            } else {
                if (categories.contains(CouponCategory.MANJIAN)
                        && categories.contains(CouponCategory.ZHEKOU)) {
                    result = executorMap.get(CouponCategory.ZHEKOU)
                            .computeRule(settlement);
                } else {
                    throw new CouponException("目前不支持更多该优惠券模板类型叠加");
                }
            }
        }
        return result;
    }

    /**
     * 在bean初始化之前去执行(before)
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof RuleExecutor)) {
            return bean;
        }
        RuleExecutor executor = (RuleExecutor) bean;

        CouponCategory ruleFlag = executor.ruleConfig();

        if (executorMap.containsKey(ruleFlag)) {
            throw new IllegalStateException("集合已经包含该类型的执行器:" +
                    ruleFlag);
        }
        log.info("初始化{}类型的执行器{}到Map集合.",
                executor.getClass(), ruleFlag);
        executorMap.put(ruleFlag, executor);
        return null;
    }

    /**
     * 在bean初始化之后去执行(after)
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
